package com.logic.modular.game.alliance.domain;

import com.alibaba.fastjson2.JSONObject;
import com.comment.exception.ServiceException;
import com.logic.comment.util.RedisUtils;
import com.logic.config.netty.web.service.MessageService;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

import static com.logic.modular.game.GameConstant.PVP_MATCH_ALLIANCE_PANEL_KEY;

/**
 * 联盟面板
 */
@Slf4j
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AlliancePanel {
    private Long matchId;
    /**
     * 玩家加入的联盟信息
     * k:玩家id v:联盟编号
     */
    public Map<String, String> playerIds = new HashMap<>();
    /**
     * 联盟信息
     * k:连盟编号 v:联盟信息
     */
    public Map<String, AllianceStatus> info = new HashMap<>();


    public static boolean insert(AlliancePanel alliancePanel) {
        Long matchId = alliancePanel.getMatchId();
        String key = String.format(PVP_MATCH_ALLIANCE_PANEL_KEY, matchId);
        if (RedisUtils.redisUtils().hasKey(key)) {
            log.error("{}:已存在,新增失败", key);
            return false;
        }
        RedisUtils.redisUtils().set(key, alliancePanel, 2, TimeUnit.HOURS);
        return true;
    }

    public static boolean update(AlliancePanel alliancePanel) {
        String key = String.format(PVP_MATCH_ALLIANCE_PANEL_KEY, alliancePanel.getMatchId());
        if (!RedisUtils.redisUtils().hasKey(key)) {
            log.error("{}:不存在,更新失败", key);
            return false;
        }
        alliancePanel.clear();
        RedisUtils.redisUtils().set(key, alliancePanel, 2, TimeUnit.HOURS);
        JSONObject jsonObject = MessageService.updateJsonObject("alliancePanel", alliancePanel);
        MessageService.sendMessageToMatch(alliancePanel.getMatchId(), jsonObject);
        return true;
    }

    public static AlliancePanel get(Long matchId) {
        String key = String.format(PVP_MATCH_ALLIANCE_PANEL_KEY, matchId);
        return (AlliancePanel) RedisUtils.redisUtils().get(key);
    }

    public static AlliancePanel tryInit(Long matchId) {
        AlliancePanel alliancePanel = get(matchId);
        if (alliancePanel == null) {
            alliancePanel = new AlliancePanel();
            alliancePanel.setMatchId(matchId);
            alliancePanel.setInfo(new HashMap<>());
            alliancePanel.setPlayerIds(new HashMap<>());
            boolean insert = insert(alliancePanel);
            if (!insert) {
                alliancePanel = get(matchId);
            }
        }
        return alliancePanel;
    }

    public boolean refuse(Long playerId, String no) {
        AllianceStatus allianceStatus = info.get(no);
        allianceStatus.info.remove(playerId.toString());
        if (allianceStatus.info.size() == 1) {
            info.remove(no);
        }
        info.put(no, allianceStatus);
        return update(this);
    }

    public void clear() {
        Set<String> startPlayerIds = playerIds.keySet();
        for (String startPlayerId : startPlayerIds) {
            info.forEach((k, v) -> {
                if (v.getInfo().containsKey(startPlayerId) && v.getStatus() == 0) {
                    v.info.remove(startPlayerId);
                    info.put(k, v);
                }
            });
        }
    }


    /**
     * 离开联盟
     *
     * @param playerId 离开联盟
     * @return 0:离开未开始的联盟成功 1:成功离开成功的联盟
     */
    public boolean leaveTheAlliance(Long playerId) {
        String playerIdString = playerId.toString();
        // 离开联盟
        if (!playerIds.containsKey(playerIdString)) {
            String no = playerIds.get(playerIdString);
            for (String joinPlayerId : info.get(no).getInfo().keySet()) {
                playerIds.remove(joinPlayerId);
            }
            info.remove(no);
            return update(this);
        }
        return false;
    }

    public static final String newAllianceKey = "pvpMatch:%d:newAlliance";
    public static final String new_Delete_AllianceKey = "pvpMatch:%d:deleteAlliance";

    public boolean tryAlliance(
            Long playerId,// 同意
            Long targetPlayerId // 目标
    ) {
        String playerIdString = playerId.toString();
        String targetPlayerIdString = targetPlayerId.toString();

        if (playerIds.containsKey(playerIdString)) {
            throw new ServiceException("你已加入同盟");
        }
        if (playerIds.containsKey(targetPlayerIdString)) {
            throw new ServiceException("目标已加入同盟");
        }

        boolean b = false;
        AtomicReference<String> targetNo = new AtomicReference<>("");
        // 判定是否处于同一未开始的同盟关系
        info.forEach((k, v) -> {
            if (v.info.containsKey(playerIdString) && v.info.containsKey(targetPlayerIdString)) {// 处于同一未开始的联盟
                targetNo.set(k);
            }
        });
        String targetNoValue = targetNo.get();
        if (!targetNoValue.isEmpty()) {
            AllianceStatus v = info.get(targetNoValue);
            v.info.put(playerIdString, 1);
            int sum = v.info.values().stream().mapToInt(item -> item).sum();
            if (sum == 2) {
                v.setStatus(1);
            }
            info.put(targetNoValue, v);
            v.getInfo().keySet().forEach(k -> playerIds.put(k, targetNoValue));
            b = true;
        } else {
            String no = null;
            Set<String> strings = info.keySet();
            for (int i = 1; i < 8; i++) {
                if (!strings.contains(String.valueOf(i))) {
                    no = String.valueOf(i);
                    break;
                }
            }
            AllianceStatus allianceStatus = new AllianceStatus();
            allianceStatus.info.put(playerIdString, 1);
            allianceStatus.info.put(targetPlayerIdString, 0);
            allianceStatus.setStatus(0);
            info.put(no, allianceStatus);
        }
        update(this);
        return b;
    }
}
